package no.sachmuld.methodcombination.api.reflection.component;

import no.sachmuld.methodcombination.api.BehaviourChain;
import no.sachmuld.methodcombination.api.BehaviourMethod;

import java.lang.reflect.Method;

/**
 *
 */
public class BeforeMethodCombination <B> extends DelegatingMethodCombination<B, Void> {

    @Override
    public BeforeMethodCombination build(final Class behaviourClass, Method targetMethod) {

        final BehaviourMethod beforeMethod = new BehaviourMethod.Builder(behaviourClass, targetMethod, false).prefix("before").returnType(Void.TYPE).build();

        validatedAgainst(beforeMethod);

        executedBy(new AbstractMethodCombination<B, Void>() {
            @Override
            public Void execute(Object target, BehaviourChain<? extends B> behaviourChain, Object... parameters) {
                if (beforeMethod.exists()) {
                    for (Object behaviour : behaviourChain.bottomUp()) {
                        if (behaviourClass.isAssignableFrom(behaviour.getClass())) {
                            beforeMethod.invoke(behaviour, parameters);
                        }
                    }
                }
                return null;
            }
        });

        return this;

    }

}
